package com.ocom.exposeapi.controller;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ocom.common.HttpUtils;
import com.ocom.common.constant.ExposeApiUrl;
import com.ocom.common.entity.card.EntityXfAccountInfo;
import com.ocom.common.entity.company.EntityComDockApi;
import com.ocom.common.request.company.GetReplyApiParaRequest;
import com.ocom.common.request.company.GetSeverReplyApiParaRequest;
import com.ocom.common.request.exposeapi.boczhxy.*;
import com.ocom.common.resp.Result;
import com.ocom.common.utils.AES;
import com.ocom.common.utils.RSAUtils;
import com.ocom.common.vo.company.SrvCodeVo;
import com.ocom.common.vo.human.UserListRVo;
import com.ocom.common.vo.human.UserListVo;
import com.ocom.common.vo.pay.UpdateListRechargeVo;
import com.ocom.exposeapi.feign.CompanyClientService;
import com.ocom.exposeapi.feign.HumanFeignService;
import com.ocom.exposeapi.feign.PayConfigClientService;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;


import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;


@RestController
@Slf4j
public class BoczhxyController {


    //中国银行转账接口地址
    public static final String URL = "https://cloud.bankofchina.com/yn/smartSchool/transToMer";


    @Autowired
    private CompanyClientService companyClientService;

    @Autowired
    private HumanFeignService humanFeignService;

    @Autowired
    private PayConfigClientService payConfigClientService;

    /**
     * 4.13.1身份验证
     *
     * @return
     */
    @PostMapping(ExposeApiUrl.URL_ExposeApi_boczhxy_queryBill)
    public String boczhxyQueryBill(@RequestBody SecretStep2 request) {
        log.info("身份验证报文:{}", request.toString());
        GetSeverReplyApiParaRequest getSeverReplyApiParaRequest = new GetSeverReplyApiParaRequest();
        getSeverReplyApiParaRequest.setDockCode("boczhxy");
        getSeverReplyApiParaRequest.setDockApiCode("boczhxy#queryBill");
        //  4 服务方私钥
        getSeverReplyApiParaRequest.setKeyType(2);
        getSeverReplyApiParaRequest.setSvrAppid("boczhxy");

        String cipherText = null;

        Result result = companyClientService.getSeverReplyApiPara(getSeverReplyApiParaRequest);
        if (result.getCode() == 4) {
            return "{\"retCode\":\"" + "0000002" + "\",\"retMsg\":\"" + "学校未开放权限" + "\"}";
        }

        if (result.getCode() == 200) {
            SrvCodeVo srvCodeVo = JSON.parseObject(JSON.toJSONString(result.getData()), SrvCodeVo.class);
            log.info("【中国银行公钥1】【{}】", srvCodeVo);
            //解密后的报文
            String plainText = SecretUtil.decrypt(JSON.toJSONString(request), srvCodeVo.getKey());
            SecretStep1 secretStep1 = JSON.parseObject(plainText, SecretStep1.class);
            String plainText1 = secretStep1.getPlainText();
            Object parse = JSON.parse(plainText1);
            String string = parse.toString();

            AuthenticationRequest authenticationRequest = JSON.parseObject(string, AuthenticationRequest.class);

            GetReplyApiParaRequest getReplyApiParaRequest = new GetReplyApiParaRequest();
            getReplyApiParaRequest.setDockCode("boczhxy");
            getReplyApiParaRequest.setDockApiCode("boczhxy#queryBill");
            getReplyApiParaRequest.setComAppid(authenticationRequest.getMerNo());
            // 1 请求方公钥
            getReplyApiParaRequest.setKeyType(1);
            getReplyApiParaRequest.setSvrAppid("boczhxy");
            Result replyApiPara = companyClientService.getReplyApiPara(getReplyApiParaRequest);
            log.info("【中国银行公钥2】【{}】【{}】", getReplyApiParaRequest,replyApiPara);
            if (result.getCode() == 4) {
                return "{\"retCode\":\"" + "0000002" + "\",\"retMsg\":\"" + "学校未开放权限" + "\"}";
            }
            EntityComDockApi entityComDockApi = JSON.parseObject(JSON.toJSONString(replyApiPara.getData()), EntityComDockApi.class);
            if (result.getCode() ==200) {
                //原始签名
                String sign = secretStep1.getSign();
                //验签
                boolean verify = RSAService.verify(plainText1, sign, entityComDockApi.getKey());
                log.info("验签结果:{}", verify);
                if (!verify) {
                    return "{\"retCode\":\"" + "0000001" + "\",\"retMsg\":\"" + "验签失败" + "\"}";
                }
            }
            UserListVo userListVo = new UserListVo();
            userListVo.setPCode(authenticationRequest.getUserNo());
            userListVo.setComId(srvCodeVo.getComId());
            userListVo.setPage(1);
            userListVo.setSize(1);
            userListVo.setStatus(0);
            Result result1 = humanFeignService.GetPersonnelList(userListVo);
            log.info("【中国银行公钥2】【{}】【{}】", userListVo,result1);
            JSONObject object = JSONObject.parseObject(JSON.toJSONString(result1.getData()));
            JSONArray jsonArray = object.getJSONArray("list");
            if (ObjectUtil.isEmpty(jsonArray)) {
                return "{\"retCode\":\"" + "0000004" + "\",\"retMsg\":\"" + "用户不存在" + "\"}";
            }

            for (Object user : jsonArray) {
                UserListRVo userListRVo = JSONObject.parseObject(JSON.toJSONString(user), UserListRVo.class);
                Result result2 = payConfigClientService.GetXFAccount(userListRVo.getComId(), Math.toIntExact(userListRVo.getPId()));
                JSONObject jsonObject1 = JSONObject.parseObject(JSON.toJSONString(result2.getData()));
                if (ObjectUtil.isEmpty(jsonObject1)) {
                    return "{\"retCode\":\"" + "0000005" + "\",\"retMsg\":\"" + "用户账户异常" + "\"}";
                }
                //加密
                EntityXfAccountInfo entityXfAccountInfo = JSONObject.parseObject(JSON.toJSONString(jsonObject1), EntityXfAccountInfo.class);
                String cardNo = entityXfAccountInfo.getAccountNo();
                String userNo = userListRVo.getPCode();
                BigDecimal balance = new BigDecimal(entityXfAccountInfo.getAccountRechargeMoney());

                JSONObject jsonObject2 = new JSONObject();
                jsonObject2.put("retCode", "0000000");
                jsonObject2.put("retMsg", "交易成功");
                jsonObject2.put("cardNo", cardNo);
                jsonObject2.put("userNo", userNo);
                jsonObject2.put("balance", balance.divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN));
                jsonObject2.put("idNumber",userListRVo.getPIdentity()==null?userNo:userListRVo.getPIdentity());
                jsonObject2.put("userName",userListRVo.getPName());

                //加密加签
                cipherText = SecretUtil.encrypt(JSON.toJSONString(jsonObject2), srvCodeVo.getKey(), entityComDockApi.getKey());

            }
        }
        return cipherText;
    }


    @PostMapping(ExposeApiUrl.URL_ExposeApi_boczhxy_chargeBill)
    public String boczhxyChargeBill(@RequestBody SecretStep2 request) {

        log.info("充值通知报文:{}", request.toString());
        GetSeverReplyApiParaRequest getSeverReplyApiParaRequest = new GetSeverReplyApiParaRequest();
        getSeverReplyApiParaRequest.setDockCode("boczhxy");
        getSeverReplyApiParaRequest.setDockApiCode("boczhxy#chargeBill");
        // 4 服务方私钥
        getSeverReplyApiParaRequest.setKeyType(2);
        getSeverReplyApiParaRequest.setSvrAppid("boczhxy");


        Result result = companyClientService.getSeverReplyApiPara(getSeverReplyApiParaRequest);
        if (result.getCode() == 4) {
            return "{\"retCode\":\"" + "0000002" + "\",\"retMsg\":\"" + "学校未开放权限" + "\"}";
        }
        String cipherText = null;

        if (result.getCode() == 200) {
            SrvCodeVo srvCodeVo = JSON.parseObject(JSON.toJSONString(result.getData()), SrvCodeVo.class);
            log.info("【中国银行公钥3】【{}】", srvCodeVo);
            //解密后的报文
            String plainText = SecretUtil.decrypt(JSON.toJSONString(request), srvCodeVo.getKey());
            SecretStep1 secretStep1 = JSON.parseObject(plainText, SecretStep1.class);
            String plainText1 = secretStep1.getPlainText();
            Object parse = JSON.parse(plainText1);
            String string = parse.toString();

            AuthenticationRequest authenticationRequest = JSON.parseObject(string, AuthenticationRequest.class);

            GetReplyApiParaRequest getReplyApiParaRequest = new GetReplyApiParaRequest();
            getReplyApiParaRequest.setDockCode("boczhxy");
            getReplyApiParaRequest.setDockApiCode("boczhxy#chargeBill");
            getReplyApiParaRequest.setComAppid(authenticationRequest.getMerNo());
            // 1 请求方公钥
            getReplyApiParaRequest.setKeyType(1);
            getReplyApiParaRequest.setSvrAppid("boczhxy");
            Result replyApiPara = companyClientService.getReplyApiPara(getReplyApiParaRequest);
            if (result.getCode() == 4) {
                return "{\"retCode\":\"" + "0000002" + "\",\"retMsg\":\"" + "学校未开放权限" + "\"}";

            }
            EntityComDockApi entityComDockApi = JSON.parseObject(JSON.toJSONString(replyApiPara.getData()), EntityComDockApi.class);
            if (result.getCode() == 200) {
                //原始签名
                String sign = secretStep1.getSign();

                //验签
                boolean verify = RSAService.verify(plainText1, sign, entityComDockApi.getKey());
                log.info("验签结果:{}", verify);
                if (!verify) {
                    return "{\"retCode\":\"" + "0000001" + "\",\"retMsg\":\"" + "验签失败" + "\"}";
                }

            }
            UserListVo userListVo = new UserListVo();
            userListVo.setPCode(authenticationRequest.getUserNo());
            userListVo.setComId(srvCodeVo.getComId());
            userListVo.setPage(1);
            userListVo.setSize(1);
            userListVo.setStatus(0);

            Result result1 = humanFeignService.GetPersonnelList(userListVo);
            log.info("【中国银行公钥4】【{}】【{}】", userListVo,result1);

            JSONObject object = JSONObject.parseObject(JSON.toJSONString(result1.getData()));
            JSONArray jsonArray = object.getJSONArray("list");
            if (ObjectUtil.isEmpty(jsonArray)) {
                return "{\"retCode\":\"" + "0000004" + "\",\"retMsg\":\"" + "用户不存在" + "\"}";
            }
            //UserListRVo userListRVo = (UserListRVo) jsonArray.get(0);
            for (Object user : jsonArray) {
                UserListRVo userListRVo = JSONObject.parseObject(JSON.toJSONString(user), UserListRVo.class);
                Result result2 = payConfigClientService.GetXFAccount(userListRVo.getComId(), Math.toIntExact(userListRVo.getPId()));
                if (ObjectUtil.isEmpty(result2.getData())) {
                    return "{\"retCode\":\"" + "0000005" + "\",\"retMsg\":\"" + "用户账户异常" + "\"}";
                }

                //人账户充值
                UpdateListRechargeVo updateListRechargeVo = new UpdateListRechargeVo();
                BigDecimal bigDecimal = new BigDecimal(authenticationRequest.getTranAmt());
                BigDecimal tranAmt = bigDecimal.multiply(BigDecimal.valueOf(100));
                updateListRechargeVo.setRechargeMoney(tranAmt.longValue());
                updateListRechargeVo.setComId(userListRVo.getComId());
                updateListRechargeVo.setFrom(2);
                updateListRechargeVo.setPId(userListRVo.getPId());
                updateListRechargeVo.setDockApiCode("boczhxy#chargeBill");
                updateListRechargeVo.setOrderNo(authenticationRequest.getTraceNo());
                updateListRechargeVo.setTypeNo(3);
                updateListRechargeVo.setTypeName("网站");
                Result result3 = payConfigClientService.UpdateListRecharge(updateListRechargeVo);
                if (result3.getCode() != 200) {
                    log.info("【充值失败】【{}】",result3.getMsg());
                    return "{\"retCode\":\"" + "0000006" + "\",\"retMsg\":\"" + "充值失败" + "\"}";
                }

                JSONObject jsonObject2 = new JSONObject();
                jsonObject2.put("retCode", "0000000");
                jsonObject2.put("retMsg", "充值成功");
                jsonObject2.put("tranRetMsg", "交易成功");
                jsonObject2.put("tranRetCode", "00");
                //加密 加签
                cipherText = SecretUtil.encrypt(JSON.toJSONString(jsonObject2), srvCodeVo.getKey(), entityComDockApi.getKey());
            }
        }
        return cipherText;

    }
    /**
     * 商户分账
     *
     * @param request
     * @return
     * @throws Exception
     */
    @PostMapping(ExposeApiUrl.UEL_ExposeApi_boczhxy_confirmTrace)
    public Result confirmTrace(@RequestBody AuthenticationRequest request) {

        log.info("中行转账 记录 【{}】",request);

        String tranDate = request.getTranDate();

        if(ObjectUtil.isNotEmpty(request.getTranInfo())) {
            List<TranInfo> tranInfoList = request.getTranInfo();
            tranInfoList.forEach(tranInfo -> {
                String tranAmt = tranInfo.getTranAmt();
                BigDecimal bigDecimal = new BigDecimal(tranAmt);
                BigDecimal multiply = bigDecimal.multiply(new BigDecimal("0.01"));
                String str = JSON.toJSONString(multiply);
                tranInfo.setTranAmt(str);
                request.setTranInfo(tranInfoList);
            });
        }

        String cipherText = null;
        Result result = null;

        GetSeverReplyApiParaRequest getSeverReplyApiParaRequest = new GetSeverReplyApiParaRequest();
        getSeverReplyApiParaRequest.setDockCode("boczhxy");
        getSeverReplyApiParaRequest.setDockApiCode("boczhxy#confirmTrace");
        // 2 请求方私钥
        getSeverReplyApiParaRequest.setKeyType(2);
        getSeverReplyApiParaRequest.setSvrAppid("boczhxy");
        result = companyClientService.getSeverReplyApiPara(getSeverReplyApiParaRequest);
        if (result.getCode() == 200) {
            SrvCodeVo srvCodeVo = JSON.parseObject(JSON.toJSONString(result.getData()), SrvCodeVo.class);
            log.info("【中国银行私钥4】【{}】",srvCodeVo);
            if (ObjectUtil.isNotEmpty(srvCodeVo)) {
                GetReplyApiParaRequest getReplyApiParaRequest = new GetReplyApiParaRequest();
                //服务方公钥
                getReplyApiParaRequest.setKeyType(1);
                getReplyApiParaRequest.setDockCode("boczhxy");
//                getReplyApiParaRequest.setComAppid(request.getMerNo());
                getReplyApiParaRequest.setSvrAppid("boczhxy");
                getReplyApiParaRequest.setDockApiCode("boczhxy#confirmTrace");
                getReplyApiParaRequest.setComId(request.getComId().longValue());
                Result replyApiPara = companyClientService.getReplyApiPara(getReplyApiParaRequest);
                if (replyApiPara.getCode() == 200) {
                    EntityComDockApi entityComDockApi = JSON.parseObject(JSON.toJSONString(replyApiPara.getData()), EntityComDockApi.class);
                    if (ObjectUtil.isNotEmpty(entityComDockApi)) {
                        //加签 加密
                        request.setTranDate(request.getTranDate().replace("-",""));
                        cipherText = SecretUtil.encrypt(JSON.toJSONString(request), srvCodeVo.getKey(), entityComDockApi.getKey());
                        SecretStep2 secretStep2 = JSON.parseObject(cipherText, SecretStep2.class);
                        HashMap<String, Object> map = new HashMap<>();
                        map.put("cipherText", secretStep2.getCipherText());
                        map.put("skey", secretStep2.getSkey());
                        //调用中国转账接口
                        String postJson = HttpUtils.postJson(URL, map);
                        log.info("请求中国转账接口返回结果为：" + postJson);
                        //使用服务方私钥 解密
                        if(result.getCode()==200){
                            log.info("【中国银行服务方私钥】【{}】",srvCodeVo);
                            String plainText = SecretUtil.decrypt(postJson, srvCodeVo.getKey());
                            SecretStep1 secretStep1 = JSON.parseObject(plainText, SecretStep1.class);
                            String plainText1 = secretStep1.getPlainText();
                            Object parse = JSON.parse(plainText1);
                            String string = parse.toString();
                            log.info("中国银行号转账 请求参数  【{}】  返回 【{}】", request, string);
                            AuthenticationRequest authenticationRequest = JSON.parseObject(string, AuthenticationRequest.class);
                            //元转分
                            if(ObjectUtil.isNotEmpty(authenticationRequest.getTranInfo())) {
                                List<TranInfo> tranInfoList = authenticationRequest.getTranInfo();
                                tranInfoList.forEach(tranInfo -> {
                                    String tranAmt = tranInfo.getTranAmt();
                                    BigDecimal bigDecimal = new BigDecimal(tranAmt);
                                    BigDecimal multiply = bigDecimal.multiply(new BigDecimal("100"));
                                    String str = JSON.toJSONString(multiply);
                                    tranInfo.setTranAmt(str);
                                    authenticationRequest.setTranInfo(tranInfoList);
                                });
                            }

                            //（因为是转账结果，可以不验签）
                           // 更新转账结果：调用3.0微服务-消费配置2.84更新商户每日转账结果（updateConsMerchPayReports）
                            authenticationRequest.setTranDate(tranDate);
                            authenticationRequest.setComId(request.getComId());
                            result = payConfigClientService.updateConsMerchPayReports(authenticationRequest);
                    }
                    }
                }
            }
        }
        return result;
    }

    public static void main(String[] args){

//
//        byte[] bytes1 = CryptoUtils.parsePrivateKey("30820277020100300D06092A864886F70D0101010500048202613082025D02010002818100E2723C7C47E70C28AD0DFC58F49E462E8008F985C6E00AEB9C736BA35BB05FC1F2E3D28C7104CD75FEA9429AA8F8ACE76AB9ABD96A66E28576CF6EAC167C62F50F992DB1B54C729747F3BCD5EDEA3E67D649D24EFE67B1731A4F0E860A0A11387B4BD3FF74C95D51809D7BC96340DDA5A50CA24DF47256FF20C1A35CBB2F61290203010001028180599F40D527580875E8D80A31E2CEE993E9D4A37D10D3073F6CF2397DB4024043F0AFBE5B1B37FD615FE2F99B6098DB45D3F59C50364E7604C09B2480337E13638F7C75B56BBF478D2ED09FA2D5EA2C258FFEF7309F7FCD70B94B3126709B4F52B2797CE0F85C420FA3F04058A53D58E3D607D4C96F2C84EC0072AD9715FA6BE9024100FBC2994801F18A50E091D38B2E4F304DFBBD12037EA3379060952DD7A711449E774A5B9B5E7B3178C8FDC5A10EC16CA25292AAF5BF62D48790B3F471B2B6F327024100E64280BBE189D0A4755711E6B6B6881CDA49B968F185757068525C2796BB225465986C76BF94014A19ABA19EA6E8E85D85A4E937E9FDFFF701A08B3B4C337B2F0241009D0080629D83AA0441E7EF0AAEF887613A8A703F69AC13AC9FEEA84602540C7CDE5BAAC13BAC8BEF8D386514C984EA60582A4B1F321949FCB8CAE0B83F0144A5024100BA2A8CA0DB122CF1BAB9620CD22F344F77A1E1D95A64D7F5C132CDB56865F6B49BCBA7EE3EA8B07E33D113840D5903FE113EAB1CFCFFD302E77AE0F7597DCA1B02402B61888DFF3BD66165B464E48CA694B83CFE1E5D72949D98C571652FEE67A553405C1064722D732513CB7B321148DC56624F27A8C55A31A8316EE0256EA8156F");
//
//        //私钥
//        PrivateKey privateKey = CryptoUtils.getPrivateKey(bytes1);
//
//        byte[] bytes2 = CryptoUtils.parsePublicKey("30819F300D06092A864886F70D010101050003818D0030818902818100E2723C7C47E70C28AD0DFC58F49E462E8008F985C6E00AEB9C736BA35BB05FC1F2E3D28C7104CD75FEA9429AA8F8ACE76AB9ABD96A66E28576CF6EAC167C62F50F992DB1B54C729747F3BCD5EDEA3E67D649D24EFE67B1731A4F0E860A0A11387B4BD3FF74C95D51809D7BC96340DDA5A50CA24DF47256FF20C1A35CBB2F61290203010001");
//
//        //公钥
//        PublicKey publicKey = CryptoUtils.getPublicKey(bytes2);
//
////        JSONObject jsonObject = new JSONObject();
//        //原始报文
//        String json="{\"tranCode\": \"Flow0003\", \"merNo\": \"ynzhxy\", \"traceNo\": \"12345678\", \"uuid\": \"8413f63a-6ff4-4142-9a7b-d6514343c914\", \"tranDate\": \"20230901\", \"tranInfo\": [{\"merNo\": \"mer01\", \"tranAmt\":\"1.00\"}, {\"merNo\": \"mer02\", \"tranAmt\":\"2.00\"}]}";
////        jsonObject.put("hhhh", "Flow0001");
////        jsonObject.put("merNo", "ynzhxy");
////        jsonObject.put("traceNo", "12345678");
////        jsonObject.put("cardType", "3");
////        jsonObject.put("userNo", "001");
//
////        String jsonString = JSON.toJSONString(jsonObject);
//        //签名
//        JSONObject jsonObject2 = JSON.parseObject(json);
//        String jsonString = JSON.toJSONString(jsonObject2);
//        String sign = CryptoUtils.sign(jsonString, privateKey);
//
//        jsonObject2.put("sign", sign);
//
//        String jsonString2 = JSON.toJSONString(jsonObject2);
//
////        String jsonString2 = JSON.toJSONString(jsonObject);
//        //签名后的报文
//        System.out.println("签名：" + sign);
//        //获取随机对称密钥
//        SecretKey secretKey = AES.generateSecretKey();
//
//        //使用对称密钥对加签的报文进行对称加密
//        String secretKey1 = CryptoUtils.getSecretKey(secretKey);
//
//        String cipherText = CryptoUtils.encryptMessage(jsonString2, secretKey1);
//        byte[] decode = Base64.getDecoder().decode(cipherText);
//        String s1 = RSAUtils.bytesToHexString(decode);
//
//        System.out.println("对称密钥加密后的报文" + s1);
//
//        //使用公钥对对称密钥进行加密
//        String skey = CryptoUtils.encryptKey(secretKey, publicKey);
//        byte[] decode1 = Base64.getDecoder().decode(skey);
//        String s11 = RSAUtils.bytesToHexString(decode1);
//
//        System.out.println("使用公钥加密后的对称密钥：" + s11);
//
//        JSONObject jsonObject1 = new JSONObject();
//        jsonObject1.put("cipherText", cipherText);
//        jsonObject1.put("skey", skey);
//        String jsonString1 = JSON.toJSONString(jsonObject1);
//        System.out.println("加密后的报文：" + jsonString1);
//
//        //解密  使用私钥对 skey解密
//
//        SecretKey secretKey2 = CryptoUtils.decryptKey(s11, privateKey);
//        System.out.println("解密后的对称密钥" + secretKey2);
//        String secretKey3 = CryptoUtils.getSecretKey(secretKey2);
//
//        String s = CryptoUtils.decryptMessage(s1, secretKey3);
//        System.out.println("解密后的报文" + s);
//
//        //验签
//        jsonObject2.put("sign",null);
//        String jsonString3 = jsonObject2.toJSONString();
//        boolean b = CryptoUtils.verifySignature(publicKey, jsonString3, sign);
//        System.out.println(b);
//    }
    }
}
